package com.taotao.druid.visitor;

import com.alibaba.druid.DbType;
import com.alibaba.druid.sql.ast.statement.*;
import com.alibaba.druid.sql.dialect.mysql.ast.MySqlKey;
import com.alibaba.druid.sql.dialect.mysql.ast.MySqlPrimaryKey;
import com.alibaba.druid.sql.dialect.mysql.ast.MySqlUnique;
import com.alibaba.druid.sql.visitor.SchemaStatVisitor;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;

/**
 * 解析建表语句来获取表结构信息
 */

@Slf4j
public class MysqlCreateTableSchemaStatVisitor extends SchemaStatVisitor {

    public MysqlCreateTableSchemaStatVisitor() {
        super(DbType.mysql);
    }

    @Getter
    private TableInfo tableInfo;


    //访问表定义
    @Override
    public boolean visit(SQLCreateTableStatement x) {

        tableInfo = new TableInfo();

        String tableName = x.getName().toString();
        String tableComment = x.getComment().toString();
        log.info("----------------tableName={},tableComment={}", tableName, tableComment);
        tableInfo.setTableName(tableName);
        tableInfo.setTableComment(tableComment);


        for (SQLTableElement e : x.getTableElementList()) {
            if (e instanceof SQLColumnDefinition) {
                visitSQLColumnDefinition((SQLColumnDefinition) e);
                continue;
            }

            if (e instanceof MySqlPrimaryKey) {
                // 主键索引声明
                visitMySqlPrimaryKey((MySqlPrimaryKey) e);
                continue;
            } else if (e instanceof MySqlUnique) {
                // 唯一索引声明
                visitMySqlUnique((MySqlUnique) e);
                continue;
            } else if (e instanceof MySqlKey) {
                // 普通索引声明
                visitMySqlKey((MySqlKey) e);
                continue;
            }

        }


        return super.visit(x);
    }


    /**
     * 唯一索引
     *
     * @param e
     */
    private void visitMySqlUnique(MySqlUnique e) {
        if (null == tableInfo.getIndexList()) {
            tableInfo.setIndexList(new HashSet<>());
        }


        List<String> cols = new ArrayList<>();
        for (SQLSelectOrderByItem col : e.getColumns()) {
            cols.add(col.toString());

        }
        log.info("Unique={},cols={}", e.getName(), cols);

        tableInfo.getIndexList().add(new IndexInfo(e.getName().toString(), cols, true));
    }


    /**
     * 普通索引
     *
     * @param e
     */
    private void visitMySqlKey(MySqlKey e) {
        if (null == tableInfo.getIndexList()) {
            tableInfo.setIndexList(new HashSet<>());
        }


        List<String> cols = new ArrayList<>();
        for (SQLSelectOrderByItem col : e.getColumns()) {
            cols.add(col.toString());
        }

        log.info("normal key={},cols={}", e.getName(), cols);


        tableInfo.getIndexList().add(new IndexInfo(e.getName().toString(), cols, false));


    }


    /**
     * 主键索引
     *
     * @param e
     */
    private void visitMySqlPrimaryKey(MySqlPrimaryKey e) {

        List<String> cols = new ArrayList<>();
        for (SQLSelectOrderByItem col : e.getColumns()) {
            cols.add(col.toString());

        }
        log.info("PrimaryKey:{},cols={}", e.getName(), cols);


        if (null == tableInfo.getPkList()) {
            tableInfo.setPkList(new HashSet<>());
        }

        tableInfo.getPkList().addAll(cols);

    }


    //访问列定义
    private void visitSQLColumnDefinition(SQLColumnDefinition x) {

        if (null == tableInfo.getColumnList()) {
            tableInfo.setColumnList(new HashSet<>());
        }

        String columnName = x.getName().toString();
        // 插入 获取列信息的代码
        String comment = x.getComment() == null ? null : x.getComment().toString();
        boolean nullable = true;
        List<SQLColumnConstraint> constraintList = x.getConstraints();
        if (null != constraintList && constraintList.size() > 0) {
            for (SQLColumnConstraint c : constraintList) {
                if (c instanceof SQLNotNullConstraint) {
                    nullable = false;
                    continue;
                }

                if (c instanceof SQLNotNullConstraint) {
                    nullable = true;
                    continue;
                }
            }

        }

        log.info("-----------------------columnName={},comment={},datatype={},autoIncrement={},pk={},nullable={},OnUpdate={},defaultVal={}",
                columnName, comment, x.getDataType().toString(), x.isAutoIncrement(), x.isPrimaryKey(), nullable, x.getOnUpdate() != null, x.getDefaultExpr());


        ColumnInfo col = new ColumnInfo();
        col.setColumnComment(columnName);
        col.setColumnType(comment);
        col.setColumnType(x.getDataType().toString());
        col.setAutoIncrement(x.isAutoIncrement());
        col.setPk(x.isPrimaryKey());
        col.setNotNull(!nullable);
        col.setOnUpdate(x.getOnUpdate() != null);
        col.setDefaultVal(x.getDefaultExpr() != null ? x.getDefaultExpr().toString() : null);

        tableInfo.getColumnList().add(col);
    }


}